import os
import shutil
import subprocess
import re
class starcarCommandTool:
    def __init__(self):
        # 初始化代码（如果有的话）
        pass
    def check_braces_matching(self,code):
        """
        检测字符串中的大括号是否匹配。

        参数:
        code (str): 要检测的代码字符串。

        返回:
        bool: 如果大括号匹配，则返回True，否则返回False。
        """
        stack = []
        for char in code:
            if char == '{':
                stack.append(char)
            elif char == '}':
                if not stack:
                    # 如果遇到右大括号时栈为空，则没有匹配的左大括号
                    return False
                stack.pop()
        # 如果栈为空，则所有大括号都正确匹配
        return len(stack) == 0
# 获取代码块        
    def remove_rust_markdown_code_block(self,text1):
        # 创建正则表达式来匹配代码块的内容
        re_pattern = r"```rust(.*?)```"
        
        # 使用findall方法来查找所有匹配的内容
        code_blocks = re.findall(re_pattern, text1, re.DOTALL)
        if not code_blocks:
            return None
        # 返回所有代码块的内容列表
        return code_blocks[0]
    
    def remove_markdown_code_block(self,text1):
        # 创建正则表达式来匹配代码块的内容
        re_pattern = r"```(.*?)```"
        
        # 使用findall方法来查找所有匹配的内容
        code_blocks = re.findall(re_pattern, text1, re.DOTALL)
        
        # 返回所有代码块的内容列表
        return code_blocks[0]
    def extract_rust_file_name(self,error_message):
        # 使用正则表达式查找以 .rs 结尾的文件名
        file_name_match1 = re.search(r'(?<=-->\s).+?\\([^:\\n]+)(?=:)', error_message, re.DOTALL)
        file_name_match = re.search( r'-->\s+.*?\\([^:\\n]+)(?=:)', error_message, re.DOTALL)
       
        if file_name_match:
            file_name = file_name_match.group(1)  # 使用 group(1) 来获取最后一个文件名
            print(file_name)
            return file_name
        else:
            print("No match found")
            return None
#执行指令
    def execute(self,command):
        """
        Run a command in the command line and return its output.

        Args:
        command (str): The command to run.

        Returns:
        str: The output of the command.
        """
        try:
            output = subprocess.check_output(command, shell=True).decode('utf-8')
            return output
        except subprocess.CalledProcessError as e:
            return f"An error occurred: {e}"
# 清除源文件内容，写入文本到文件    
    def write_text_to_file(self,text, file_path):
        """
        Write the given text to the specified file path.
        If the file does not exist, it will be created.
        If the file exists, the text will be appended to the end of the file.

        Args:
        text (str): The text to write to the file.
        file_path (str): The path of the file where the text will be written.
        """
        # 确保out文件夹存在
        out_directory = os.path.dirname(file_path)
        if not os.path.exists(out_directory):
            os.makedirs(out_directory)
        with open(file_path, 'w') as file:
            file.write(text + '\n')
#使用c2rust
    def transpile_c_to_rust(self,input_dir, output_dir):
        """
        Transpile C files to Rust using c2rust.

        Args:
        input_dir (str): The directory containing the C source files.
        output_dir (str): The directory to output the transpiled Rust files.

        Returns:
        str: The output of the command.
        """
        command = f"./c2rust/c2rust transpile {input_dir}/*.c {input_dir}/*.h -o {output_dir}"
        try:
            output = subprocess.check_output(command, shell=True).decode('utf-8')
            return output
        except subprocess.CalledProcessError as e:
            return f"An error occurred: {e}"
  #使用c2rust  
    def transpile_cpp_to_rust(self,input_dir, output_dir):
        """
        Transpile C files to Rust using c2rust.

        Args:
        input_dir (str): The directory containing the C source files.
        output_dir (str): The directory to output the transpiled Rust files.

        Returns:
        str: The output of the command.
        """
        command = f"./c2rust/c2rust transpile {input_dir}/*.cpp {input_dir}/*.h -o {output_dir}"
        try:
            output = subprocess.check_output(command, shell=True).decode('utf-8')
            return output
        except subprocess.CalledProcessError as e:
            return f"An error occurred: {e}"
 #移动文件   
    def move_files_by_name(self,source_dir, target_dir, reference_dir):
        """
        根据参考目录中的文件名，将源目录中的同名文件移动到目标目录。

        :param source_dir: 源目录路径
        :param target_dir: 目标目录路径
        :param reference_dir: 参考目录路径
        """
        # 确保目标目录存在
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)

        # 获取参考目录中的所有文件名（忽略后缀）
        reference_files = [os.path.splitext(file_name)[0].replace('-', '_') for file_name in os.listdir(reference_dir)]


        for file_name in reference_files:
            # 构建源文件和目标文件的完整路径
            for source_file in os.listdir(source_dir):
                source_file_name, source_file_extension = os.path.splitext(source_file)
                if source_file_name == file_name:
                    source_file_path = os.path.join(source_dir, source_file)
                    target_file_path = os.path.join(target_dir, source_file)

                    # 检查源文件是否存在
                    if os.path.exists(source_file_path):
                        # 移动文件
                        shutil.move(source_file_path, target_file_path)
                        print(f"文件 '{source_file}' 已从 '{source_dir}' 移动到 '{target_dir}'")
                    else:
                        print(f"源文件 '{source_file_path}' 不存在")
                    break  # 找到匹配的文件后，跳出循环
#生成库文件lib.rs
    def generate_lib_rs(self,folder_path):
        """
        遍历指定文件夹中的文件名，并根据这些文件名生成对应的Rust `lib.rs` 文件内容。

        :param folder_path: 要遍历的文件夹路径
        :return: 生成的 `lib.rs` 文件内容
        """
        # 获取文件夹中的所有文件和文件夹
        items = os.listdir(folder_path)

        # 过滤出文件名，并忽略文件扩展名
        file_names = [os.path.splitext(item)[0] for item in items if os.path.isfile(os.path.join(folder_path, item)) and item not in ['lib.rs', 'main.rs']]


        # 生成Rust `lib.rs` 文件内容
        lib_rs_content = ""
        for file_name in file_names:
            lib_rs_content += f"mod {file_name};\n"
         # 写入文件前先清空文件内容
        with open(os.path.join(folder_path, "lib.rs"), 'w') as file:
            file.write(lib_rs_content)

        return lib_rs_content
 #检测rust项目   
    def build_rust_project(self, directory):
        """
        在指定目录执行 cargo build 命令。

        :param directory: 要编译的 Rust 项目的目录路径。
        :return: (success, output) 元组，其中 success 是一个布尔值，表示编译是否成功，output 是编译过程的输出信息。
        """
        try:
            result = subprocess.run(['cargo', 'check'], cwd=directory, capture_output=True, text=True, check=True)
            if "error" in result.stdout:
                return False, result.stdout
            return True, result.stdout
        except subprocess.CalledProcessError as e:
            return False, e.stderr


  #执行cargo build  
    def check_rust_project(self, directory):
        """
        在指定目录执行 cargo build 命令。

        :param directory: 要编译的 Rust 项目的目录路径。
        :return: (success, output) 元组，其中 success 是一个布尔值，表示编译是否成功，output 是编译过程的输出信息。
        """
        try:
            result = subprocess.run(['cargo', 'check'], cwd=directory, capture_output=True, text=True, check=True)
            if "error" in result.stdout:
                return False, result.stdout
            return True, result.stdout
        except subprocess.CalledProcessError as e:
            return False, e.stderr
   #测试rust项目         
    def test_rust_project(self,directory):
        """
        在指定目录执行 cargo build 命令。

        :param directory: 要编译的 Rust 项目的目录路径。
        :return: (success, output) 元组，其中 success 是一个布尔值，表示编译是否成功，output 是编译过程的输出信息。
        """
        try:
            result = subprocess.run(['cargo', 'test'], cwd=directory, capture_output=True, text=True, check=True)
            if "error" in result.stdout:
                return False, result.stdout
            return True, result.stdout
        except subprocess.CalledProcessError as e:
            return False, e.stderr
  #创建cargo.toml  
    def create_cargo_toml(self,directory):
        """
        在指定目录中创建一个默认的 cargo.toml 文件。

        :param directory: 要创建 cargo.toml 文件的目录路径。
        """
        cargo_toml_content = """
        [package]
        name = "my_project"
        version = "0.1.0"
        edition = "2021"

        [dependencies]
        libc = "0.2"
        """

        if not os.path.exists(directory):
            os.makedirs(directory)

        # 创建 cargo.toml 文件
        file_path = os.path.join(directory, "cargo.toml")
        with open(file_path, "w") as file:
            file.write(cargo_toml_content)

        print(f"cargo.toml 文件已创建在 {file_path}")
#分割rust函数
    def find_rust_functions(self,text):
            # 使用正则表达式匹配Rust函数定义
        functions = re.findall(r'fn [a-zA-Z_][a-zA-Z0-9_]*\(.*?\) {.*?}', text, re.DOTALL)
        return functions
#读取rust函数        
    def read_and_split_rust_functions(self,file_path):
  # 读取文件内容
        with open(file_path, 'r') as file:
            rust_text = file.read()
                
                # 分割函数文本
            rust_functions = self.split_rust_functions(rust_text)
                
            return rust_functions              
   #对文件进行操作     
    def modify_text(self,operation, text, start_line, end_line, content):
            """
            根据操作类型对文本的特定行进行操作。

            :param operation: 操作类型，可以是 'add', 'delete' 或 'modify'
            :param text: 输入的文本，是一个字符串列表，每行一个元素
            :param start_line: 起始行号（包含）
            :param end_line: 结束行号（包含）
            :param content: 操作内容，对于 'add' 是要添加的文本，对于 'modify' 是要替换的文本
            :return: 修改后的文本
            """
            # 确保行号在文本范围内
            start_line = max(0, start_line)
            end_line = min(len(text), end_line)

            if operation == 'add':
                # 在指定行后添加内容
                text = text[:end_line + 1] + [content] + text[end_line + 1:]
            elif operation == 'delete':
                # 删除指定行
                text = text[:start_line] + text[end_line + 1:]
            elif operation == 'modify':
                # 修改指定行
                for i in range(start_line, end_line + 1):
                    text[i] = content
            else:
                raise ValueError("Invalid operation type. Choose 'add', 'delete', or 'modify'.")

            return text
    
    def count_errors_in_message(self,message):
        """
        This function takes an error message as input and returns the number of errors.
        
        Args:
        message (str): The error message string.
        
        Returns:
        int: The number of errors found in the message.
        """
        # 使用正则表达式匹配错误个数
        error_count_match = re.search(r'due to (\d+) previous error', message)
        
        # 检查是否找到匹配项，并提取错误个数
        if error_count_match:
            return int(error_count_match.group(1))
        else:
            return 0
    def split_rust_functions(self,code):
        """
        Split a Rust code into its individual functions by matching braces.

        :param code: A string containing the Rust code.
        :return: A list of function texts as strings.
        """
        lines = code.split('\n')
        functions = []
        brace_count = 0
        function_start = None
        function_start_count = False
        for i, line in enumerate(lines):
            if 'fn ' in line :
                function_start = i
            if  function_start is not None:
                brace_count += line.count('{')
                if brace_count > 0 and function_start is not None:
                    function_start_count=True
                brace_count -= line.count('}')

            if brace_count == 0 and function_start is not None and function_start_count:
                functions.append('\n'.join(lines[function_start:i + 1]))
                function_start = None
                function_start_count=False

        return functions    
    
    def extract_error_details(self,error_text):
                # 正则表达式模式，用于匹配错误信息中的行号和错误描述
        #pattern = r"error.+?:\d\n"
        pattern = r"error.+?\n.+?:\d+\n.+?\n\n"
        # 使用正则表达式查找所有匹配项
        matches = re.findall(pattern, error_text,re.DOTALL)

 # 存储错误详情的字典
        error_details = {}
        
        # 遍历所有匹配项
        for match in matches:
            # 提取行号和列号
            line_column = re.search(r":(\d+):(\d+)", match)
            if line_column:
                line_number = line_column.group(1)
                column_number = line_column.group(2)
            else:
                continue  # 如果没有匹配到行号和列号，则跳过该匹配项
            
          
            
            # 添加错误详情到字典
            error_details[line_number] = match
        
        return error_details
    
    def split_error_messages(self,error_text):
        # 正则表达式模式，用于匹配独立的错误信息块
        # 匹配以 'error:' 开头，直到下一个 'error:' 或文本末尾
        pattern = r"error.+?\n.+?:\d+\n.+?\n\n"
        
        # 使用正则表达式查找所有匹配项
        matches = re.findall(pattern, error_text,re.DOTALL)
        
        return matches
    #获取函数名
    def get_function_names(self,text):
        pattern = r'fn\s+([A-Za-z_][A-Za-z0-9_]*)\s*'
        return re.findall(pattern, text)
    #根据行数找到函数
    def find_function_around_line_in_rust(self,code, line_number):
            """
            Find the function text around a given line number in a Rust code by matching 'fn' keywords.

            :param code: A string containing the Rust code.
            :param line_number: The line number to find the function around.
            :return: A tuple containing the function text and the line numbers of the start and end of the function.
            """
            lines = code.split('\n')
            if line_number < 1 or line_number > len(lines):
                return "Line number out of range.", None, None

            # Find the start of the function
            start_line = line_number - 1
            while start_line > 0 and 'fn ' not in lines[start_line].strip():
                start_line -= 1

            # Find the end of the function by looking for the next 'fn' keyword
            end_line = line_number
            while end_line < len(lines) and 'fn ' not in lines[end_line].strip():
                end_line += 1

            # Extract the function text, excluding the next 'fn' keyword line
            function_text = '\n'.join(lines[start_line:end_line])
            return function_text, start_line + 1, end_line
    
    def find_content_around_line_in_rust(self,code, line_number, context_lines=3):
        lines = code.split('\n')
        # 计算起始和结束行号，同时处理越界
        start_line = max(line_number - context_lines, 0)
        end_line = min(line_number + context_lines + 1, len(lines))

        # 提取指定范围内的行
        content_around_line = '\n'.join(lines[start_line:end_line])
        
        return content_around_line
    
    def execute_python_code(self,code):
        # 定义一个字典来存储执行结果
        local_vars = {}
        
        try:
            # 使用exec来执行代码，除了表达式之外的代码
            exec(code, {}, local_vars)
            
            # 如果有返回值，假设它存储在变量'result'中
            if 'result' in local_vars:
                return local_vars['result']
            else:
                # 如果没有显式的返回值，则返回None
                return None
        except Exception as e:
            # 如果执行过程中发生异常，返回异常信息
            return f"An error occurred: {e}"

    def remove_rust_prefix_from_file(self,file_path):
        try:
            # 读取文件内容
            with open(file_path, 'r') as file:
                content = file.read()
            
            # 检查文件内容是否以 "rust" 开头
            if content.startswith('rust'):
                # 去掉 "rust" 开头
                content = content[len('rust'):]
            
            # 将修改后的内容写回文件
            with open(file_path, 'w') as file:
                file.write(content)
                
            print(f'Updated file: {file_path}')
        except FileNotFoundError:
            print(f'File not found: {file_path}')
        except Exception as e:
            print(f'An error occurred: {e}')